/*
 * 
 *  Este arquivo é parte do software TODO Calculadora. TODO Calculadora é um software livre;
 *  você pode redistribui-lo e/ou modifica-lo dentro dos termos da Licença Pública Geral GNU
 *  como publicada pela Fundação do Software Livre (FSF); na versão 2 da Licença,
 *  ou (na sua opnião) qualquer versão.
 *  
 *	Este programa é distribuido na esperança que possa ser útil, mas SEM NENHUMA GARANTIA;
 *  sem uma garantia implícita de ADEQUAÇÂO a qualquer MERCADO ou APLICAÇÃO EM PARTICULAR.
 *  Veja a Licença Pública Geral GNU para maiores detalhes. Você deve ter recebido uma cópia
 *  da Licença Pública Geral GNU junto com este programa, se não, escreva para a Fundação do
 *	Software Livre(FSF)
 *
 *	Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package numeros.divisibilidade.mdc;

public final class MaximoDivisorComum {

	/**
	 * Valor inicial dos restos utilizados para operação de cálculo Máximo
	 * Divisor Comum (M.D.C)
	 */
	private static final long VALOR_INICIAL_RESTO = new java.util.Random()
			.nextLong();

	/**
	 * Realiza o cálculo de dois números para encontrar o máximo dividor comum
	 * (M.D.C) com o uso da estratégia de divisões sucessivas. Chama os métodos
	 * com os dois passos da estratégia.
	 * 
	 * @param primeiroElemento
	 *            Primeiro número utilizado
	 * @param segundoElemento
	 *            Segundo número utilizado
	 * @return Máximo divisor comum (M.D.C) entre os dois números
	 *         (primeiroElemento, segundoElemento)
	 */
	public static final Number calculaMaximoDivisorComum(
			Number primeiroElemento, Number segundoElemento) {

		long resto = VALOR_INICIAL_RESTO;
		return executaPrimeiroPassoCalculoMDC(primeiroElemento,
				segundoElemento, resto);

	}

	/**
	 * Executa o primeiro passo da estratégia de divisões sucessivas. Esse passo
	 * verifica quais dos dois números é maior e divide o mesmo pelo menor. Logo
	 * após isso armazena o resto para uso no segundo passo da estratégia
	 * 
	 * @param primeiroElemento
	 *            Primeiro elemento (número) informado
	 * @param segundoElemento
	 *            Segundo elemento (número) informado
	 * @return Retorna com a chamada do método
	 *         <b>executaSegundoPassoCalculoMDC</b>
	 */
	private static Number executaPrimeiroPassoCalculoMDC(
			Number primeiroElemento, Number segundoElemento, Number resto) {

		long numeroUM = primeiroElemento.longValue();
		long numeroDOIS = segundoElemento.longValue();

		long novoResto = VALOR_INICIAL_RESTO;

		if (numeroUM > numeroDOIS) {
			resto = numeroUM % numeroDOIS;
			return executaSegundoPassoCalculoMDC(numeroDOIS, resto, novoResto);
		} else {
			resto = numeroDOIS % numeroUM;
			return executaSegundoPassoCalculoMDC(numeroUM, resto, novoResto);
		}
	}

	/**
	 * Executa o segundo passo da estratégia de divisões sucessivas que consiste
	 * de executar recursivamente o cálculo entre o divisor da primeira
	 * estratégia pelo resto atual, até que o novo resto seja zero. Com essa
	 * premissa sendo verdadeira, retorna-se o último resto que será considerado
	 * o Máximo Divisor Comum (M.D.C);
	 * 
	 * @param divisor
	 *            Divisor da primeira estratégia
	 * @param resto
	 *            Resto da divisão da primeira estratégia
	 * @param novoResto
	 *            Novo Resto, resultante da divisão entre o divisor e resto
	 * 
	 * @return Máximo divisor comum (M.D.C)
	 */
	private static Number executaSegundoPassoCalculoMDC(Number divisor,
			Number resto, long novoResto) {
		novoResto = divisor.longValue() % resto.longValue();

		if (novoResto == 0) {
			return resto;
		} else {
			divisor = resto;
			resto = novoResto;
			return executaSegundoPassoCalculoMDC(divisor, resto, novoResto);
		}
	}
}
